﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataStuctureStudy.Sorts
{
    class HeapSort<T>
        where T : IComparable<T>
    {
        public static void Test()
        {
            var items = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
            HeapSort<int>.Sort(items);
            Console.WriteLine(String.Join(",", items));
        }

        public static void Sort(T[] items)
        {
            for (int i = items.Length / 2 - 1; i >= 0; i--)
            {
                MoveDown(items, i, items.Length - 1);
            }

            for (var i = items.Length - 1; i >= 0; i--)
            {
                items[i] = Remove(items, i);
            }
        }

        private static T Remove(T[] items, int endIndex)
        {
            var result = items[0];
            items[0] = items[endIndex];

            MoveDown(items, 0, endIndex - 1);

            return result;
        }

        private static void MoveDown(T[] items, int startIndex, int endIndex)
        {
            var top = items[startIndex];
            var current = startIndex;

            while (current <= endIndex)
            {
                var large = 0;
                var left = 2 * current + 1;
                var right = left + 1;

                if (left <= endIndex && right <= endIndex)
                {
                    if (items[left].CompareTo(items[right]) >= 0)
                    {
                        large = left;
                    }
                    else
                    {
                        large = right;
                    }
                }
                else if (left <= endIndex)
                {
                    large = left;
                }
                else
                {
                    break;
                }

                if (items[large].CompareTo(top) <= 0)
                {
                    break;
                }

                items[current] = items[large];
                current = large;
            }

            items[current] = top;
        }
    }
}
